@file:JvmName("UrlUtils")

package cc.z8g.browser.utils

import android.util.Patterns
import android.webkit.URLUtil
import cc.z8g.browser.core.BrowserConst
import cc.z8g.browser.html.AbsListPageFactory.BOOKMARKS_FILE_NAME
import cc.z8g.browser.html.AbsListPageFactory.HISTORY_FILE_NAME
import cc.z8g.browser.html.AbsListPageFactory.WEB_RES_FILE_NAME
import java.util.Locale
import java.util.regex.Pattern

/**
 * Attempts to determine whether user input is a URL or search terms.  Anything with a space is
 * passed to search if [canBeSearch] is true.
 *
 * Converts to lowercase any mistakenly upper-cased scheme (i.e., "Http://" converts to
 * "http://")
 *
 * @param canBeSearch if true, will return a search url if it isn't a valid  URL. If false,
 * invalid URLs will return null.
 * @return original or modified URL.
 */
fun smartUrlFilter(url: String, canBeSearch: Boolean, searchUrl: String): String {
    var inUrl = url.trim()
    val hasSpace = inUrl.contains(' ')
    val matcher = ACCEPTED_URI_SCHEMA.matcher(inUrl)
    if (matcher.matches()) {
        // force scheme to lowercase
        val scheme = requireNotNull(matcher.group(1)) { "matches() implies this is non null" }
        val lcScheme = scheme.toLowerCase(Locale.getDefault())
        if (lcScheme != scheme) {
            inUrl = lcScheme + matcher.group(2)
        }
        if (hasSpace && Patterns.WEB_URL.matcher(inUrl).matches()) {
            inUrl = inUrl.replace(" ", URL_ENCODED_SPACE)
        }
        return inUrl
    }
    if (!hasSpace) {
        if (Patterns.WEB_URL.matcher(inUrl).matches()) {
            return URLUtil.guessUrl(inUrl)
        }
    }

    return if (canBeSearch) {
        URLUtil.composeSearchUrl(inUrl, searchUrl, QUERY_PLACE_HOLDER)
    } else {
        ""
    }
}

/**
 * True if the URL is a file URL, false otherwise.
 */
fun String?.isFileUrl(): Boolean = this != null && this.startsWith(BrowserConst.FILE)

/** 返回给定 URL 是否内部url */
fun String?.isInnerUrl(): Boolean =
    this != null && this.startsWith(BrowserConst.FILE) &&
            (this.endsWith(BOOKMARKS_FILE_NAME) || this.endsWith(HISTORY_FILE_NAME) || this.endsWith(WEB_RES_FILE_NAME))

/**
 * Determines if the url is a url for the bookmark page.
 *
 * @return true if the url is a bookmark url, false otherwise.
 */
fun String?.isBookmarkUrl(): Boolean =
    this != null && this.startsWith(BrowserConst.FILE) && this.endsWith(BOOKMARKS_FILE_NAME)


fun String?.isWebResUrl(): Boolean = this != null && this.startsWith(BrowserConst.FILE) && this.endsWith(WEB_RES_FILE_NAME)

/**
 * Determines if the url is a url for the history page.
 *
 * @return true if the url is a history url, false otherwise.
 */
fun String?.isHistoryUrl(): Boolean =
    this != null && this.startsWith(BrowserConst.FILE) && this.endsWith(HISTORY_FILE_NAME)

private val ACCEPTED_URI_SCHEMA =
    Pattern.compile("(?i)((?:http|https|file)://|(?:inline|data|about|javascript):|(?:.*:.*@))(.*)")
const val QUERY_PLACE_HOLDER = "%s"
private const val URL_ENCODED_SPACE = "%20"
